using Microsoft.Win32;
using System;
using System.Drawing;
using System.Windows.Forms;

class Program {
    static void Main(){
        // Application.Run(new SysForm());
        // Application.Run(new SysInfoPanel());
        Application.Run(new SysInfoScroll());
    }
}

class SysForm : Form {
    public SysForm(){
        Text = "系统信息展示v1";
        BackColor = SystemColors.Window;
        ForeColor = SystemColors.WindowText;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        var g = e.Graphics;
        // sys1(g);
        // sys2(g);
        sys3(g);
    }

    void sys1(Graphics g){
        var b = new SolidBrush(ForeColor);
        int y = 0;
        g.DrawString("ArrangeDirection:"+SystemInformation.ArrangeDirection
            ,Font,b,0,y);

        g.DrawString("ArrangeStartingPosition:"+SystemInformation.ArrangeStartingPosition
        ,Font,b,0,y+=Font.Height);

        g.DrawString("BootMode:"+SystemInformation.BootMode
        ,Font,b,0,y+=Font.Height);

        g.DrawString("Border3DSize:"+SystemInformation.Border3DSize
        ,Font,b,0,y+=Font.Height);

        g.DrawString("BorderSize:"+SystemInformation.BorderSize
        ,Font,b,0,y+=Font.Height);
    }

    void sys2(Graphics g){
        var b = new SolidBrush(ForeColor);
        SizeF sizef;
        float cxCol,y = 0;
        int cySpace;

        sizef = g.MeasureString("ArrangeStartingPosition:",Font);
        cxCol = sizef.Width;
        cySpace = Font.Height;

        g.DrawString("ArrangeDirection:"
            ,Font,b,0,y);
        g.DrawString(SystemInformation.ArrangeDirection.ToString()
            ,Font,b,cxCol,y);

        y += cySpace;

        g.DrawString("ArrangeStartingPosition:"
        ,Font,b,0,y);

        g.DrawString(SystemInformation.ArrangeStartingPosition.ToString()
        ,Font,b,cxCol,y);

        y += cySpace;

        g.DrawString("BootMode:"
        ,Font,b,0,y);
        g.DrawString(SystemInformation.BootMode.ToString()
        ,Font,b,cxCol,y);

        y += cySpace;

        g.DrawString("Border3DSize:"
        ,Font,b,0,y);
        g.DrawString(SystemInformation.Border3DSize.ToString()
        ,Font,b,cxCol,y);

        y += cySpace;

        g.DrawString("BorderSize:"
        ,Font,b,0,y);

        g.DrawString(SystemInformation.BorderSize.ToString()
        ,Font,b,cxCol,y);

    }

     float cxCol;
     int cySpace;

    void sys3(Graphics g){
        var b = new SolidBrush(ForeColor);
        int iCount = SysInfoStrings.Count;
        var labels = SysInfoStrings.Labels;
        var values = SysInfoStrings.Values;

        var sizef = g.MeasureString("",Font);
        cxCol = sizef.Width + SysInfoStrings.MaxLabelWidth(g,Font);
        cySpace = Font.Height;

        for (int i = 0; i < iCount; i++)
        {
            g.DrawString(labels[i],Font,b,0,i*cySpace);
            g.DrawString(values[i],Font,b,cxCol,i*cySpace);
        }
    }
}

class SysInfoPanel:Form{
    float cxCol;
    int cySpace;

    public SysInfoPanel(){
        Text = "SystemInfo Panel";
        BackColor = SystemColors.Window;
        ForeColor = SystemColors.WindowText;
        AutoScroll = true;

        // 计算
        Graphics g = CreateGraphics();
        var sizef = g.MeasureString("",Font);
        cxCol = sizef.Width + SysInfoStrings.MaxLabelWidth(g,Font);
        cySpace = Font.Height;

        var panel = new Panel();
        panel.Parent = this;
        panel.Paint += new PaintEventHandler(PanelOnPaint);
        panel.BackColor = Color.Honeydew;
        panel.Location = Point.Empty;
        panel.Size = new Size(
            (int)Math.Ceiling(cxCol + SysInfoStrings.MaxValueWidth(g,Font)),
            (int)Math.Ceiling(cySpace * SysInfoStrings.MaxValueWidth(g,Font))
        );
        g.Dispose();
    }

    void PanelOnPaint(object obj,PaintEventArgs e){
        var g = e.Graphics;
        var b = new SolidBrush(ForeColor);
        var iCount = SysInfoStrings.Count;
        var labels = SysInfoStrings.Labels;
        var values = SysInfoStrings.Values;
        for (int i = 0; i <iCount; i++)
        {
            g.DrawString(labels[i],Font,b,0,i*cySpace);
            g.DrawString(values[i],Font,b,cxCol,i*cySpace);
        }
    }
}

class SysInfoScroll:Form {
    float cxCol;
    int cySpace;
    public SysInfoScroll(){
        Text = "SystemInfo Panel";
        BackColor = SystemColors.Window;
        ForeColor = SystemColors.WindowText;
        AutoScroll = true;

        // 计算
        // Graphics g = CreateGraphics();
        // var sizef = g.MeasureString("",Font);
        // cxCol = sizef.Width + SysInfoStrings.MaxLabelWidth(g,Font);
        // cySpace = Font.Height;

        // AutoScrollMinSize = new Size(
        //     (int)Math.Ceiling(cxCol + SysInfoStrings.MaxValueWidth(g,Font)),
        //     (int)Math.Ceiling(cySpace * SysInfoStrings.MaxValueWidth(g,Font))
        // );

        Graphics g = CreateGraphics();
        var sizef = g.MeasureString("",Font);
        cxCol = sizef.Width + SysInfoReflectionStrings.MaxLabelWidth(g,Font);
        cySpace = Font.Height;

        AutoScrollMinSize = new Size(
            (int)Math.Ceiling(cxCol + SysInfoReflectionStrings.MaxValueWidth(g,Font)),
            (int)Math.Ceiling(cySpace * SysInfoReflectionStrings.MaxValueWidth(g,Font))
        );

        g.Dispose();
    }

    protected override void OnPaint(PaintEventArgs e){
        var g = e.Graphics;
        var b = new SolidBrush(ForeColor);
        // var iCount = SysInfoStrings.Count;
        // var labels = SysInfoStrings.Labels;
        // var values = SysInfoStrings.Values;

        var iCount = SysInfoReflectionStrings.Count;
        var labels = SysInfoReflectionStrings.Labels;
        var values = SysInfoReflectionStrings.Values;

        var pt = AutoScrollPosition;

        for (int i = 0; i <iCount; i++)
        {
            g.DrawString(labels[i],Font,b,pt.X,pt.Y+i*cySpace);
            g.DrawString(values[i],Font,b,pt.X+cxCol,pt.Y+i*cySpace);
        }
    }
}

class SysInfoStrings{
    public static string[] Labels{
        get{
            return new string[]{
                "ArrangeDirection",
                "ArrangeStartingPosition",
                "BootMode",
                "Border3DSize",
                "BorderSize"
            };
        }
    }
    public static string[] Values {
        get{
            return new string[] {
                SystemInformation.ArrangeDirection.ToString(),
                SystemInformation.ArrangeStartingPosition.ToString(),
                SystemInformation.BootMode.ToString(),
                SystemInformation.Border3DSize.ToString(),
                SystemInformation.BorderSize.ToString(),
            };
        }
    }
    public static int Count{
        get {
            return Labels.Length;
        }
    }

    static float MaxWidth(string[] strs,Graphics g,Font f){
        float fMax = 0;
        foreach(var str in strs){
            fMax = Math.Max(fMax,g.MeasureString(str,f).Width);
        }
        return fMax;
    }
    public static float MaxLabelWidth(Graphics g,Font f){
        return MaxWidth(Labels,g,f);
    }
    public static float MaxValueWidth(Graphics g,Font f){
        return MaxWidth(Values,g,f);
    }
}


class SysInfoReflectionStrings
{
    static bool bValidInfo = false;
    static int iCount;
    static string[] labels;
    static string[] values;

    static SysInfoReflectionStrings(){
        SystemEvents.UserPreferenceChanged += 
            new UserPreferenceChangedEventHandler(UserPreferenceChanged);
        SystemEvents.DisplaySettingsChanged += 
            new EventHandler(DisplaySettingsChanged);
    }

    static void UserPreferenceChanged(object obj,UserPreferenceChangedEventArgs ea){
        bValidInfo = false;
    }
    static void DisplaySettingsChanged(object obj,EventArgs ea){
        bValidInfo = false;
    }
    static void GetSysInfo(){
        if(bValidInfo){
            return;
        }

        var type = typeof(SystemInformation);
        var props = type.GetProperties();
        iCount = 0;
        foreach (var p in props)
        {
            if(p.CanRead && p.GetGetMethod().IsStatic){
                iCount = iCount + 1;
            }
        }
        labels = new string[iCount];
        values = new string[iCount];

        iCount = 0;
        foreach (var p in props)
        {
            if(p.CanRead && p.GetGetMethod().IsStatic){
                labels[iCount] = p.Name;
                values[iCount] = p.GetValue(type,null).ToString();
                iCount = iCount + 1;
            }
        }
        Array.Sort(labels,values);
        bValidInfo = true;
    }

    public static string[] Labels{
        get{
            GetSysInfo();
            return labels;
        }
    }
    public static string[] Values{
        get{
            GetSysInfo();
            return values;
        }
    }
    public static int Count{
        get{
            GetSysInfo();
            return iCount;
        }
    }

    static float MaxWidth(string[] strs,Graphics g,Font f){
        float fMax = 0;
        foreach(var str in strs){
            fMax = Math.Max(fMax,g.MeasureString(str,f).Width);
        }
        return fMax;
    }
    public static float MaxLabelWidth(Graphics g,Font f){
        return MaxWidth(Labels,g,f);
    }
    public static float MaxValueWidth(Graphics g,Font f){
        return MaxWidth(Values,g,f);
    }

}